if ( !strnicmp(policy->governor->name,
"userspace", CPUFREQ_NAME_LEN) )
- {
- if ( freq < policy->min )
- freq = policy->min;
- if ( freq > policy->max )
- freq = policy->max;
-
- ret = __cpufreq_driver_target(policy, freq, CPUFREQ_RELATION_L);
- }
+ ret = write_userspace_scaling_setspeed(op->cpuid, freq);
else
ret = -EINVAL;
#include <xen/sched.h>
#include <acpi/cpufreq/cpufreq.h>
-static unsigned int usr_speed;
-
/*
* cpufreq userspace governor
*/
+static unsigned int cpu_set_freq[NR_CPUS];
+
static int cpufreq_governor_userspace(struct cpufreq_policy *policy,
unsigned int event)
{
int ret = 0;
- unsigned int freq;
+ unsigned int cpu;
- if (!policy)
+ if (unlikely(!policy) ||
+ unlikely(!cpu_online(cpu = policy->cpu)))
return -EINVAL;
switch (event) {
case CPUFREQ_GOV_START:
+ if (!cpu_set_freq[cpu])
+ cpu_set_freq[cpu] = policy->cur;
+ break;
case CPUFREQ_GOV_STOP:
+ cpu_set_freq[cpu] = 0;
break;
case CPUFREQ_GOV_LIMITS:
- freq = usr_speed ? : policy->cur;
- if (policy->max < freq)
+ if (policy->max < cpu_set_freq[cpu])
ret = __cpufreq_driver_target(policy, policy->max,
CPUFREQ_RELATION_H);
- else if (policy->min > freq)
+ else if (policy->min > cpu_set_freq[cpu])
ret = __cpufreq_driver_target(policy, policy->min,
CPUFREQ_RELATION_L);
- else if (usr_speed)
- ret = __cpufreq_driver_target(policy, freq,
+ else
+ ret = __cpufreq_driver_target(policy, cpu_set_freq[cpu],
CPUFREQ_RELATION_L);
break;
return ret;
}
+int write_userspace_scaling_setspeed(unsigned int cpu, unsigned int freq)
+{
+ struct cpufreq_policy *policy = cpufreq_cpu_policy[cpu];
+
+ if (!cpu_online(cpu) || !policy)
+ return -EINVAL;
+
+ cpu_set_freq[cpu] = freq;
+
+ if (freq < policy->min)
+ freq = policy->min;
+ if (freq > policy->max)
+ freq = policy->max;
+
+ return __cpufreq_driver_target(policy, freq, CPUFREQ_RELATION_L);
+}
+
static void __init
cpufreq_userspace_handle_option(const char *name, const char *val)
{
- if (!strcmp(name, "speed") && val)
- usr_speed = simple_strtoul(val, NULL, 0);
+ if (!strcmp(name, "speed") && val) {
+ unsigned int usr_cmdline_freq;
+ unsigned int cpu;
+
+ usr_cmdline_freq = simple_strtoul(val, NULL, 0);
+ for (cpu = 0; cpu < NR_CPUS; cpu++)
+ cpu_set_freq[cpu] = usr_cmdline_freq;
+ }
}
struct cpufreq_governor cpufreq_gov_userspace = {